package cool.mtc.security.auth.jwt;

import cool.mtc.core.result.ResultConstant;
import cool.mtc.security.auth.AuthFormSupport;
import cool.mtc.security.auth.AuthTemplate;
import cool.mtc.security.auth.AuthToken;
import cool.mtc.security.data.model.UserDetailsSupport;
import cool.mtc.security.exception.AuthException;
import cool.mtc.security.plugin.jwt.JwtTemplate;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.RequiredArgsConstructor;

/**
 * @author yz
 */
@RequiredArgsConstructor
public abstract class JwtAuthTemplate extends AuthTemplate {
    protected final JwtTemplate jwtTemplate;

    @Override
    protected void handlePreCheck(AuthFormSupport formSupport) {
        JwtAuthForm form = (JwtAuthForm) formSupport;

        try {
            Claims calims = jwtTemplate.parse(form.getToken());
            form.setTokenCalims(calims);
        } catch (ExpiredJwtException ex) {
            form.setExpired(true);
            form.setTokenCalims(ex.getClaims());
        } catch (Exception ex) {
            throw new AuthException(ResultConstant.A0301);
        }

        if (!this.isTokenInAllowList(form.getToken())) {
            throw new AuthException(ResultConstant.A0311);
        }
    }

    @Override
    protected AuthToken handleResult(AuthFormSupport formSupport, UserDetailsSupport userSupport) {
        JwtAuthForm form = (JwtAuthForm) formSupport;
        String token;
        if (form.isExpired()) {
            token = this.generateToken(form.getToken(), userSupport);
        } else {
            token = form.getToken();
        }

        return new JwtAuthToken(form, token, userSupport.getAuthorities());
    }

    protected abstract boolean isTokenInAllowList(String token);

    protected abstract String generateToken(String originalToken, UserDetailsSupport userSupport);
}
